<?php
namespace app\index\controller;
use app\common\controller\PayBase;
use think\Db;
use app\index\model\ChongzhiList;
use think\Exception;

class Paysf extends PayBase
{
    private $kvs = array();
    protected $gateway_url;             //支付平台网关
    protected $mer_no;                     //这里填写商户号
    protected $mer_key;                   //这里填写签名时需要的私钥key
    protected $back_notify_url;        //这里填写支付完成后，支付平台后台通知当前支付是否成功的url
    protected $page_notify_url;       //这里填写支付完成后，页面跳转到商户页面的url，同时告知支付是否成功
    protected $pay_type;                  //支付方式 1 网银 2 微信 3 支付宝
    protected $req_referer;              //请指定当前系统的域名，用来防钓鱼
    protected $req_customer_id;     //手动设置请求消费者ip地址，主要是用于测试环境，生产环境请设置为null

    public function __construct() {
        parent::__construct();
        $this->gateway_url = 'http://pay.sufupay.vip/pay.html';
        $this->mer_no = '1494163';
        $this->mer_key = 'd621cd05dd23cf5fe57cd187bb398001';
        $this->back_notify_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/index/Paysf/payReturn';
        $this->page_notify_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/index/Paysf/payReturnStatus';
        $this->pay_type = '1';
        $this->req_referer = '103.91.126.97';
        $this->req_customer_id = null;
    }
    
	/**
	 * 速付上行支付接口
	 */
    public function initPay($username='',$pay_type='',$amount=-1,$from=0)
    {
        //接收数据
        $user = cookie('username','');
        $password = cookie('password','');
        $username =  empty($username) ? input('post.username','') : $username;
        $bank_code = empty($pay_type) ? input('post.pay_type','') : $pay_type;
        $amount = -1==$amount ? input('post.amount',0) : $amount;

        $ctime = time();
        
        if($bank_code=='null' || $bank_code=='') return packJson('','请选择支付方式',500);
        $pay_method = Db::name('pay_type_list')
            ->alias("a")
            ->join('__PAY_METHOD__ b','a.method_id=b.id','LEFT')
            ->where(['a.method'=>2,'a.type_value'=>$bank_code])
            ->field('a.type_name,b.name,b.id,b.method,b.money')->find();
        $remark = $pay_method['type_name'].'-'.$pay_method['name'];

        //验证用户信息
        if( 0==$from ){
            if(!$user || !$username || ($user!=$username)) return packJson('','用户身份验证失败',500);
            $user_info = Db::name('username')->field('id,us_class,swzh,nbzh')->where(['username'=>$username,'password'=>$password])->find();
        }else{
            $user_info = Db::name('username')->field('id,us_class,swzh,nbzh')->where(['username'=>$username])->find();
        }

        if(!$user_info) return packJson('','用户身份验证失败',500);
        if($user_info['swzh'] == 1) return packJson('','试玩账号无法充值',500);
        if($user_info['nbzh'] == 1) return packJson('','内部账号不支持线上充值',500);
        
        //充值防骚扰是否开启，并进行处理
        $harassment = Db::name('xt_czfsr')->find();
        if($harassment['open'] > 0) {
            $nowys = $ctime - $harassment['time_xs'] * 60;
            $old_czjl = Db::name('chongzhi_list')->where('username',$username)->where('cztime','>',$nowys)->find();
            if($old_czjl['id'] > 0) {
                return packJson('',"系统充值防骚扰已开启，{$harassment['time_xs']}分钟内只能充值1次！",500);
            }
        }
        
        //验证金额
        if($amount <= 0) return packJson('','请输入充值金额',500);
        if($amount < 50) return packJson('','最低充值金额为五十元人民币',500);
        if($amount > 20000) return packJson('','充值金额超过范围',500);

        //计算优惠金额
        $msje = $msbs = 0;
        $cz_set = Db::name('xt_chongzhi')->find();
        $user_class = Db::name('us_class')->where('id',$user_info['us_class'])->find();
        $zsje = $amount * $user_class['czzsbl'] / 100;
        $zsbs = $user_class['czzsbl'];
        if($amount >= $cz_set['xscz_je']) {
            $msje = $amount * $cz_set['xscz_zs'] / 100;
            $msbs = $cz_set['xscz_zs'];
        }
        //充值方案赠送
        $method_money = 0.00;
        if( floatval( $pay_method['money'] ) > 0 ){
            if( 0==intval( $pay_method['method'] ) ){
                //金额
                $method_money = $pay_method['money'];
            }else{
                //比例
                $method_money = floatval($amount) * floatval($pay_method['money']) / 100;
            }
        }
        $method_money = sprintf("%.2f",substr(sprintf("%.3f", $method_money), 0, -2));
        
        //生成订单号
        $order_sn = 'SFF' . str_pad($user_info['id'],5,'0',STR_PAD_LEFT) . $ctime . rand(111,999);
        //处理数据并生成签名
        if( 1==$from ) $this->page_notify_url.="Third";
        $this->sfAdd('notify_url', $this->back_notify_url);
        $this->sfAdd('return_url', $this->page_notify_url);
        $this->sfAdd('pay_type', $this->pay_type);
        $this->sfAdd('bank_code', $bank_code);
        $this->sfAdd('merchant_code', $this->mer_no);
        $this->sfAdd('order_no', $order_sn);
        $this->sfAdd('order_amount', $amount);
        $this->sfAdd('order_time', date('Y-m-d h:i:s',$ctime));
        $this->sfAdd('req_referer', $this->req_referer);
        $this->sfAdd('customer_ip', $this->getClientIp());
        $this->sfAdd('return_params', $username);
        $sign = $this->sfSign();
        
        //组装数据
        $data = array();
        $data['notify_url'] = $this->back_notify_url;
        $data['return_url'] = $this->page_notify_url;
        $data['pay_type'] = $this->pay_type;
        $data['bank_code'] = $bank_code;
        $data['merchant_code'] = $this->mer_no;
        $data['order_no'] = $order_sn;
        $data['order_amount'] = $amount;
        $data['order_time'] = date('Y-m-d h:i:s',$ctime);
        $data['req_referer'] = $this->req_referer;
        $data['customer_ip'] = $this->getclientip();
        $data['return_params'] = $username;
        $data['sign'] = $sign;
        //插入充值信息
        $u = Db::name('username')->where('username',$username)->value('je');
        $model = new ChongzhiList();
        if( $model->setTransRechargeInfo($order_sn,$amount,$username,0,0,1,$remark,$ctime,'速付线上支付','系统自动',get_ip(),0,$bank_code,$zsje,$zsbs,$msje,$msbs,$user_info['us_class'],'',0,$method_money,$u) ){
            //跳转支付页
            $pay_url = $this->gateway_url . '?' . http_build_query($data);
            return packJson($pay_url,'',200);
        }else{
            return packJson('',"订单生产错误",500);
        }
    }
    
    /**
     * 通知过程接口调页面
     */
    public function payReturnStatus()
    {
        $merchantCode = input('merchant_code', '');
        $orderNo = input('order_no', '');
        $orderTime = input('order_time', '');
        $orderAmount = input('order_amount', '');
        $trade_status = input('trade_status', '');
        $tradeNo = input('trade_no', '');
        $returnParams = input('return_params', '');
        $trade_time = input('trade_time', '');
        $notify_type = input('notify_type', '');
        $sign = input('sign', '');
    
        $this->sfAdd("merchant_code", $merchantCode);
        $this->sfAdd("notify_type", $notify_type);
        $this->sfAdd("order_no", $orderNo);
        $this->sfAdd("order_time", $orderTime);
        $this->sfAdd("order_amount", $orderAmount);
        $this->sfAdd("trade_status", $trade_status);
        $this->sfAdd("trade_no", $tradeNo);
        $this->sfAdd("trade_time", $trade_time);
        $this->sfAdd("return_params", $returnParams);
        $_sign = $this->sfSign();
    
        //商户系统返回HTTP状态码为200，服务器则认为通知成功，如果不为200则为失败。失败后，会陆续发送五次通知。
        if ($_sign == $sign || $trade_status == "success") {
            $this->buildHtml("充值成功，{$orderAmount} 元已到账");
            exit;
        } else {
            $this->buildHtml("充值失败");
            //失败,通知支付平台失败（状态码只要不是200就行）
            header('HTTP/1.1 404 Not Found');
            header("status: 404 Not Found");
            exit;
        }
    }
    public function payReturnStatusThird()
    {
        $merchantCode = input('merchant_code', '');
        $orderNo = input('order_no', '');
        $orderTime = input('order_time', '');
        $orderAmount = input('order_amount', '');
        $trade_status = input('trade_status', '');
        $tradeNo = input('trade_no', '');
        $returnParams = input('return_params', '');
        $trade_time = input('trade_time', '');
        $notify_type = input('notify_type', '');
        $sign = input('sign', '');

        $this->sfAdd("merchant_code", $merchantCode);
        $this->sfAdd("notify_type", $notify_type);
        $this->sfAdd("order_no", $orderNo);
        $this->sfAdd("order_time", $orderTime);
        $this->sfAdd("order_amount", $orderAmount);
        $this->sfAdd("trade_status", $trade_status);
        $this->sfAdd("trade_no", $tradeNo);
        $this->sfAdd("trade_time", $trade_time);
        $this->sfAdd("return_params", $returnParams);
        $_sign = $this->sfSign();

        //商户系统返回HTTP状态码为200，服务器则认为通知成功，如果不为200则为失败。失败后，会陆续发送五次通知。
        if ($_sign == $sign || $trade_status == "success") {
            $this->buildHtml("充值成功，{$orderAmount} 元已到账",1);
            exit;
        } else {
            $this->buildHtml("充值失败",1);
            //失败,通知支付平台失败（状态码只要不是200就行）
            header('HTTP/1.1 404 Not Found');
            header("status: 404 Not Found");
            exit;
        }
    }
    /**
     * 通知过程接口
     */
    public function payReturn()
    {
        Db::startTrans();
        $merchantCode = input('merchant_code', '');
        $orderNo = input('order_no', '');
        $orderTime = input('order_time', '');
        $orderAmount = input('order_amount', '');
        $trade_status = input('trade_status', '');
        $tradeNo = input('trade_no', '');
        $returnParams = input('return_params', '');
        $trade_time = input('trade_time', '');
        $notify_type = input('notify_type', '');
        $sign = input('sign', '');
        $ctime = time();

        $this->sfAdd("merchant_code", $merchantCode);
        $this->sfAdd("notify_type", $notify_type);
        $this->sfAdd("order_no", $orderNo);
        $this->sfAdd("order_time", $orderTime);
        $this->sfAdd("order_amount", $orderAmount);
        $this->sfAdd("trade_status", $trade_status);
        $this->sfAdd("trade_no", $tradeNo);
        $this->sfAdd("trade_time", $trade_time);
        $this->sfAdd("return_params", $returnParams);
        $_sign = $this->sfSign();

        //商户系统返回HTTP状态码为200，服务器则认为通知成功，如果不为200则为失败。失败后，会陆续发送五次通知。
        if ($_sign == $sign) {
            //更新用户金额、打码量等相关信息
            $order_info = Db::name('chongzhi_list')->where('ddbh',$orderNo)->find();
            $user_info = Db::name('username')->where('username',$returnParams)->find();
            $dml_set = Db::name('xt_dmsz')->where('id',1)->find();
            $xtcz = Db::name('xt_chongzhi')->where('id',1)->find();
            if($xtcz['dmopen'] == 1) {
                $dmls = ($order_info['hy_msje'] + $order_info['hy_zsje'] + $order_info['je']+ $order_info['method_money']) * $dml_set['xscz_dmbs'];
            }else{
                $dmls = $order_info['je'] * $dml_set['xscz_dmbs'];
            }
        	if ($trade_status == "success" && $order_info['je'] == $orderAmount) {
        	    //充值后账户总金额
        	    $czhje = $order_info['hy_msje'] + $order_info['hy_zsje'] + $order_info['je'] + $user_info['je']+ $order_info['method_money'];
        	    //充值总金额
        	    $czzje = $order_info['je'] + $user_info['czzje'];
        	    //用户当前打码量
        	    $dml = $user_info['dml'] + $dmls;
        	    try {
                    $zt = model('ChongzhiList')->where(['ddbh'=>$orderNo])->value('zt');
                    if( 1==intval($zt) ){
                        throw new Exception("该订单已经成功通知");
                    }
                    if( !model('ChongzhiList')->updateRechargeInfo($orderNo,$tradeNo,1,$czhje,$ctime) ){
                        throw new Exception("更新订单信息错误");
                    }
                    if( !model('Username')->upUserXsczInfo($czhje,$dml,$czzje,$returnParams) ){
                        throw new Exception("更新用户金额错误");
                    }
                    Db::name('username')->where('username',$order_info['username'])->setInc('cz_num');
            	    $fav_money = $order_info['hy_msje']+$order_info['hy_zsje']+ $order_info['method_money'];

                    //满送金额，等级赠送金额，充值方案赠送金额
                    $extcj = array(
                        'username'=>$user_info['username'],
                        'user_class'=>$user_info['us_class'],
                        'fstime'=>time(),
                        'czadmin' => '系统赠送',
                    );
                    $cjhje = floatval($order_info['je']) + floatval($user_info['je']) + floatval($order_info['hy_msje']);
                    if( floatval($order_info['hy_msje']) > 0 ){
                        $extcj['beizhu'] = '系统赠送，充值满送金额';
                        $extcj['cjje'] = $order_info['hy_msje'];
                        $extcj['cjhje'] = $cjhje;
                        Db::name('caijin_list')->insert($extcj);
                    }
                    $cjhje += floatval($order_info['hy_zsje']);
                    if( floatval($order_info['hy_zsje']) > 0 ){
                        $extcj['beizhu'] = '系统赠送，充值等级赠送金额';
                        $extcj['cjje'] = $order_info['hy_zsje'];
                        $extcj['cjhje'] = $cjhje;
                        Db::name('caijin_list')->insert($extcj);
                    }
                    $cjhje += floatval($order_info['method_money']);
                    if( floatval($order_info['method_money']) > 0 ){
                        $extcj['beizhu'] = '系统赠送，充值方案赠送金额';
                        $extcj['cjje'] = $order_info['method_money'];
                        $extcj['cjhje'] = $cjhje;
                        Db::name('caijin_list')->insert($extcj);
                    }

            	    $data = array('username' =>$returnParams,'test'=>"您账户充值金额：{$order_info['je']}，赠送金额：{$fav_money}。已充值到账，请注意查收！",'xx_time'=>$ctime,'ifdq'=>0);
            	    Db::name('xiaoxi')->data($data)->insert();
        	        Db::commit();
        		} catch (\Exception $e) {
        		    Db::rollback();
        		    header('HTTP/1.1 404 Not Found');
                    header("status: 404 Not Found");
        		    exit;
        		}
        	} else {
        		//失败,通知支付平台失败
        		header('HTTP/1.1 404 Not Found');
        		header("status: 404 Not Found");
        		exit;
        	}
        } else {
            //失败,通知支付平台失败（状态码只要不是200就行）
            header('HTTP/1.1 404 Not Found');
            header("status: 404 Not Found");
            exit;
        }
    }
    
    private function appendParam(& $sb, $name, $val, $and = true, $charset = null)
    {
        if ($and) {
            $sb .= "&";
        } else {
            $sb .= "?";
        }
        
        $sb .= $name;
        $sb .= "=";
        if (is_null($val)) $val = "";

        if (is_null($charset)) {
            $sb .= $val;
        } else {
            $sb .= urlencode($val);
        }
    }
    
    private function sfItems()
    {
        return $this->kvs;
    }
    
    private function sfAdd($k, $v)
    {
        if (!is_null($v)) $this->kvs[$k] = $v; 
    }
    
    private function sfSign()
    {
        //echo $this->sfLink();
        return md5($this->sfLink());
    }
    
    private function sfLink()
    {
        $strb = "";
        ksort($this->kvs);
        foreach ($this->kvs as $key => $val) {
            $this->appendParam($strb, $key, $val);
        }
        $this->appendParam($strb, 'key', $this->mer_key);
        $strb = substr($strb, 1, strlen($strb) - 1);
        return $strb;
    }
    
    private function getClientIp()
    {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        if ($this->req_customer_id != null)
            $ip = $this->req_customer_id;
        return $ip;
    }
    
}
